home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / glibc108.gz / glibc108 / glibc-1.08.1 / time / difftime.c < prev    next >
C/C++ Source or Header  |  1994-05-10  |  3KB  |  68 lines

  1. /* Copyright (C) 1991, 1994 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <time.h>
  21.  
  22.  
  23. /* Return the difference between TIME1 and TIME0.  */
  24. __CONSTVALUE
  25. double
  26. DEFUN(difftime, (time1, time0), time_t time1 AND time_t time0)
  27. {
  28.   /* Algorithm courtesy Paul Eggert (eggert@twinsun.com).  */
  29.  
  30.   time_t delta, hibit;
  31.  
  32.   if (sizeof (time_t) < sizeof (double))
  33.     return (double) time1 - (double) time0;
  34.   if (sizeof (time_t) < sizeof (LONG_DOUBLE))
  35.     return (LONG_DOUBLE) time1 - (LONG_DOUBLE) time0;
  36.  
  37.   if (time1 < time0)
  38.     return - difftime (time0, time1);
  39.  
  40.   /* As much as possible, avoid loss of precision by computing the
  41.     difference before converting to double.  */
  42.   delta = time1 - time0;
  43.   if (delta >= 0)
  44.     return delta;
  45.  
  46.   /* Repair delta overflow.  */
  47.   hibit = 1;
  48.   while ((hibit <<= 1) > 0)
  49.     continue;
  50.  
  51.   /* The following expression rounds twice, which means the result may not
  52.      be the closest to the true answer.  For example, suppose time_t is
  53.      64-bit signed int, long_double is IEEE 754 double with default
  54.      rounding, time1 = 9223372036854775807 and time0 = -1536.  Then the
  55.      true difference is 9223372036854777343, which rounds to
  56.      9223372036854777856 with a total error of 513.  But delta overflows to
  57.      -9223372036854774273, which rounds to -9223372036854774784, and
  58.      correcting this by subtracting 2 * (long_double) hibit (i.e. by adding
  59.      2**64 = 18446744073709551616) yields 9223372036854776832, which rounds
  60.      to 9223372036854775808 with a total error of 1535 instead.  This
  61.      problem occurs only with very large differences.  It's too painful to
  62.      fix this portably.  We are not alone in this problem; many C compilers
  63.      round twice when converting large unsigned types to small floating
  64.      types, so if time_t is unsigned the "return delta" above has the same
  65.      double-rounding problem.  */
  66.   return delta - 2 * (LONG_DOUBLE) hibit;
  67. }
  68.